using ICSharpCode.AvalonEdit;
using System;
using System.Windows;

namespace Sensor.UI.Binders;

/// <summary>
/// 用于AvalonEdit与ViewModel的绑定（附加属性）
/// 提供日志文本绑定和自动滚动功能
/// </summary>
public static class AvalonEditBinder
{
    /// <summary>
    /// 绑定日志文本的依赖属性
    /// 用于将ViewModel中的日志文本绑定到AvalonEdit控件
    /// </summary>
    public static readonly DependencyProperty LogTextProperty =
        DependencyProperty.RegisterAttached(
            "LogText",
            typeof(string),
            typeof(AvalonEditBinder),
            new PropertyMetadata(string.Empty, OnLogTextChanged));

    /// <summary>
    /// 自动滚动到末尾的依赖属性
    /// 控制是否在文本更新后自动滚动到文档末尾
    /// </summary>
    public static readonly DependencyProperty AutoScrollProperty =
        DependencyProperty.RegisterAttached(
            "AutoScroll",
            typeof(bool),
            typeof(AvalonEditBinder),
            new PropertyMetadata(false, OnAutoScrollChanged));

    /// <summary>
    /// 追加模式依赖属性
    /// 控制是否以追加模式更新文本（避免全量替换，提高性能）
    /// </summary>
    public static readonly DependencyProperty AppendModeProperty =
        DependencyProperty.RegisterAttached(
            "AppendMode",
            typeof(bool),
            typeof(AvalonEditBinder),
            new PropertyMetadata(false));

    /// <summary>
    /// 设置日志文本值
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <param name="value">要设置的日志文本</param>
    public static void SetLogText(TextEditor editor, string value) => 
        editor?.SetValue(LogTextProperty, value);

    /// <summary>
    /// 获取日志文本值
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <returns>当前绑定的日志文本</returns>
    public static string GetLogText(TextEditor editor) => 
        editor?.GetValue(LogTextProperty) as string ?? string.Empty;

    /// <summary>
    /// 设置自动滚动标志
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <param name="value">是否启用自动滚动</param>
    public static void SetAutoScroll(TextEditor editor, bool value) => 
        editor?.SetValue(AutoScrollProperty, value);

    /// <summary>
    /// 获取自动滚动标志
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <returns>是否启用自动滚动</returns>
    public static bool GetAutoScroll(TextEditor editor) => 
        editor?.GetValue(AutoScrollProperty) is bool value && value;

    /// <summary>
    /// 设置追加模式标志
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <param name="value">是否启用追加模式</param>
    public static void SetAppendMode(TextEditor editor, bool value) => 
        editor?.SetValue(AppendModeProperty, value);

    /// <summary>
    /// 获取追加模式标志
    /// </summary>
    /// <param name="editor">目标文本编辑器</param>
    /// <returns>是否启用追加模式</returns>
    public static bool GetAppendMode(TextEditor editor) => 
        editor?.GetValue(AppendModeProperty) is bool value && value;

    /// <summary>
    /// 自动滚动属性变化时的处理
    /// </summary>
    /// <param name="d">依赖对象</param>
    /// <param name="e">属性变化事件参数</param>
    private static void OnAutoScrollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextEditor editor && e.NewValue is true && editor.Document != null)
        {
            // 当启用自动滚动时，立即滚动到末尾
            editor.ScrollToEnd();
        }
    }

    /// <summary>
    /// 日志文本变化时更新AvalonEdit
    /// 优化性能：批量更新时暂停渲染，支持追加模式
    /// </summary>
    /// <param name="d">依赖对象（TextEditor）</param>
    /// <param name="e">属性变化事件参数</param>
    private static void OnLogTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is not TextEditor editor || e.NewValue is not string newText)
            return;

        // 确保文档存在
        if (editor.Document == null)
            return;

        // 获取当前文本用于追加模式判断
        string currentText = editor.Document.Text;
        bool isAppendMode = GetAppendMode(editor);
        bool shouldAppend = isAppendMode && 
                           !string.IsNullOrEmpty(currentText) && 
                           !string.IsNullOrEmpty(newText) && 
                           newText.StartsWith(currentText, StringComparison.Ordinal);

        // 优化性能：批量更新时暂停渲染
        editor.Document.BeginUpdate();
        try
        {
            if (shouldAppend)
            {
                // 追加模式：只添加新增的部分，提高性能
                string appendText = newText[currentText.Length..];
                if (!string.IsNullOrEmpty(appendText))
                {
                    // 使用Insert方法在文档末尾插入文本
                    editor.Document.Insert(editor.Document.TextLength, appendText);
                }
            }
            else
            {
                // 全量替换模式
                editor.Document.Text = newText ?? string.Empty;
            }

            // 自动滚动到末尾（如果启用）
            if (GetAutoScroll(editor))
            {
                // 使用ScrollToEnd确保滚动到文档末尾
                editor.ScrollToEnd();
            }
        }
        catch (ArgumentOutOfRangeException ex)
        {
            // 处理文本操作超出范围的异常
            System.Diagnostics.Debug.WriteLine($"AvalonEdit文本操作超出范围: {ex.Message}");
        }
        catch (InvalidOperationException ex)
        {
            // 处理无效操作异常
            System.Diagnostics.Debug.WriteLine($"AvalonEdit无效操作: {ex.Message}");
        }
        catch (Exception ex)
        {
            // 捕获其他异常，避免绑定错误导致应用程序崩溃
            System.Diagnostics.Debug.WriteLine($"AvalonEdit绑定错误: {ex.Message}");
        }
        finally
        {
            editor.Document.EndUpdate(); // 恢复渲染
        }
    }
}